import 'package:flutter/material.dart';
import 'package:shop/base/debounce/debounce.dart';

final Map<Function, JMDebounce> _debounceMap = <Function, JMDebounce>{};

/// Extension on the [Function]
extension JMFunctionExtension on Function {
  /// JMFunctionExtension: Get debounce function.
  /// * [duration] normal is `Duration(milliseconds: 500)`.
  JMDebounce getDebounceFn({Duration duration = const Duration(milliseconds: 500)}) {
    var debounceFn = _debounceMap[this];
    if (debounceFn == null) {
      debounceFn = JMDebounce();
      _debounceMap[this] = debounceFn;
    }
    debounceFn.delay = duration;
    return debounceFn;
  }
}

extension VoidCallbackExtension on VoidCallback {
  /// JMFunctionExtension: Add debounce for VoidCallback.
  /// * [duration] normal is `Duration(milliseconds: 500)`.
  ///
  /// Example:
  /// ```dart
  /// test().debounce()
  /// ```
  void debounce({Duration duration = const Duration(milliseconds: 500)}) {
    var debounceFn = getDebounceFn(duration: duration);
    debounceFn(() => this());
  }
}

extension ValueChangedExtension<T> on ValueChanged<T> {
  /// JMFunctionExtension: Add debounce for ValueChanged.
  /// * [duration] normal is `Duration(milliseconds: 500)`.
  ///
  /// Example:
  /// ```dart
  /// test(e).debounce(e)
  /// ```
  debounce({
    required T value,
    Duration duration = const Duration(milliseconds: 500),
  }) {
    var debounceFn = getDebounceFn(duration: duration);
    debounceFn(() => this.call(value));
  }
}
